回到昨天留下的問題
TextFiled 送出後怎麼清除裡面的字其實只要將 SingleChildScrollView wrap住 center 就可以,SingleChildScrollView可以讓widget超出容器尺寸(以這個例子來說是裝置高度)時將它變成一個滾動式的元件。
從名字上也看得出來他只接受一個child,所以大部分時候都是用在元件較小的情況下使用,但其實還是可以像這次用結合 Column 來接受複數的widgets,但實際上還是有其他widget可以達成這些需求像是 ListView 。
至於TextFiled 送出後怎麼清除裡面的字,在TextFiled 中有一個參數是 controller 。在 flutter 中蠻多互動的元件都有這個參數,來方便我們對一些互動行為有更多細節的操作,我覺得可以想像成類似 react 的 ref 的感覺。那我們就直接原本的 _MyHomePageState 裡宣告我們的控制器。
final TextEditingController _textEditingController = TextEditingController();
然後將這個 _textEditingController 給我們的 TextFiled
TextField(
decoration: const InputDecoration(labelText: '待辦事項'),
onSubmitted: (input) {
_handleAddNewTodo(input);
},
controller: _textEditingController,
),
接下來回到 _handleAddNewTodo 這個function裡
void _handleAddNewTodo(String input) {
setState(() {
_todoList = [..._todoList, input];
_textEditingController.text = '';
});
}
這時我只要在更新完 _todoList 後將 _textEditingController.text = '' 即可。
那接下來我們就來擴充這個TodoList的功能,為了之後著想所以我們的Todo應該不能只是一個 String ,所以我們先建立一個 class 來表示 Todo 。
首先先建立一個檔案 todo_model.dart
class TodoModel {
final String content;
TodoModel({required this.content});
}
然後將原本的 _todoList 改成 List<TodoModel>
List<TodoModel> _todoList = [TodoModel(content: '123')];
然後將剩下的部分都改為使用這個 class
// 迴圈渲染部分
TodoCard(
todoContent: entity.value.content,
index: entity.key,
),
// setState的部分
_todoList = [..._todoList, TodoModel(content: input)];
然後接下來先來新增移除按鈕的UI
..._todoList.asMap().entries.map(
(entity) => Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TodoCard(
todoContent: entity.value.content,
index: entity.key,
),
GestureDetector(
child: const Icon(Icons.remove),
)
],
),
),
我們將原本迴圈裡改用 Row 然後新增一個 GestureDetector 包住 Icon
GestureDetector 就是將他的child新增一些事件監聽的功能。Icon 則是一個顯示icon的widget, Icons 則是material 提供的一些常用Icon圖案。
接下來我們就來實作刪除功能
void _handleRemoveTodo(int hashCode) {
setState(() {
_todoList =
_todoList.while((value) => value.hashCode != hashCode).toList();
});
}
hashCode 是每個 instance 都有的屬性所以我們就直接拿來當作唯一識別的id。
while 類似於JS的 array.filter 當裡面的function是 ture 時則會回傳這個 value
所以整行的意思就是當 hashCode 不等於我傳入的 hashCode 都要回傳,也就是不回傳我要刪除的那個instance 。
只後再回到 GestureDetector
GestureDetector(
child: const Icon(Icons.remove),
onTap: () {
_handleRemoveTodo(entity.value.hashCode);
},
)
這樣我們就能完成了刪除功能了~

現在的程式碼開始變得有點複雜,所以還是上傳到github 供大家參考。
https://github.com/zxc469469/flutter_todo_list/tree/Day19